package scenic;

import java.awt.Rectangle;

import scenic.geom.Affine2;
import scenic.jni.Renderer;

/**
 * This is the base class for all scene graph nodes. Every node
 * with the exception of the root node has a single parent node. 
 * This means that the scene graph is tree-like in structure.
 */
public abstract class SceneNode {
	static final int safeMargin = 4;
	
	static final int DRAW_SIMPLE = 0;
	static final int DRAW_SURFACE = 1;
	static final int DRAW_SURFACE2X = 2;
	static final int DRAW_SURFACE4X = 3;
	
	SceneParent parent;
	boolean isVisible;
	
	protected SceneNode() {
	}
	
	/**
	 * Gets the parent of this scene node.
	 */
	public SceneParent getParent() {
		return parent;
	}

	/**
	 * Removes this scene node from its parent.
	 */
	public void close() {
		if(parent != null)
			parent.remove(this);
	}
	
	/**
	 * Gets the total transformation of this node. The total transformation
	 * is the cumulative transformation of this node and its ancestors.
	 */
	public Affine2 getTotalTransform() {
		if (parent != null)
			return parent.getTotalTransform();
		else
			return Affine2.identity();
	}
	
	abstract void draw(DrawContext context, Affine2 transform, Rectangle visibleArea);
	
	void prepareDraw(DrawContext context, Affine2 transform) {
	}
	
	abstract Rectangle getBounds(Affine2 transform);
	
	void setVisibility(boolean state) {
		isVisible = state;
	}
	
	protected boolean getVisibility() {
		return isVisible;
	}
	
	void changed(Rectangle area) {
		if(parent != null)
			parent.childChanged(area);
	}
	
	void changed() {
		changed(null);
	}
	
	int getDrawType(Affine2 transform) {
		return Shape.DRAW_SIMPLE;
	}
	
	static int getSurfaceType(int drawType) {
		if(drawType == DRAW_SURFACE2X)
			return Renderer.SURFACE_TYPE_ALPHA2X;
		if(drawType == DRAW_SURFACE4X)
			return Renderer.SURFACE_TYPE_ALPHA4X;
		if(drawType == DRAW_SURFACE)
			return Renderer.SURFACE_TYPE_ALPHA;
		return Renderer.SURFACE_TYPE_COLOR;
	}
	
	static Rectangle addSafeMargin(Rectangle bounds) {
		return new Rectangle(bounds.x - safeMargin, bounds.y - safeMargin, 
				bounds.width + safeMargin * 2, bounds.height + safeMargin * 2);
	}
}
